// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: linchuan

#pragma once

#include <list>
#include <string>
#include <utility>
#include <vector>

#include "coin2/base/time.h"
#include "coin2/exchange/base/api_base/asio_http_context.h"
#include "coin2/exchange/base/api_base/base_auth.h"
#include "coin2/exchange/base/api_util/api_signature.h"
#include "coin2/exchange/base/api_util/auth_key.h"
#include "coin2/exchange/base/api_util/json_writer.h"
#include "coin2/exchange/base/api_util/url_params_builder.h"

class PrexFuturesWsApiKeyAuth {
 public:
  static std::string GetExpireSeconds(int64_t delay) {
    const int64_t T = 1000000000LL;
    std::string ts_str = std::to_string(GetCurrentTimestamp() / T + delay);
    return ts_str;
  }

  static std::string GetExpireSeconds() {
    constexpr int64_t delay = 50;
    const int64_t T = 1000000000LL;
    std::string ts_str = std::to_string(GetCurrentTimestamp() / T + delay);
    return ts_str;
  }

  static std::string GetSignature(
      const std::string& secret_key,
      const std::string& query_string,
      const std::string& post_body,
      const std::string& method,
      const std::string& time) {
    if (secret_key.empty()) {
      throw std::runtime_error("[Prex] API key and secret key are required");
    }
    std::string cre = method + query_string + time + post_body;
    return ApiSignatureUtil::GetSignatureByHexHmacSHA256(cre, secret_key);
  }

 public:
  explicit PrexFuturesWsApiKeyAuth(const std::string& key_filepath)
      : key_(AuthKey::FromFile(key_filepath)) {}

  void CreateSignature(
      std::string* api_key,
      std::string* api_expires,
      std::string* api_sign,
      std::string* auth_msg) {
    *api_key = key_.access_key();
    *api_expires = GetExpireSeconds(3600 * 24);
    *api_sign = GetSignature(key_.secret_key(), "/api/v1/stream", "", "GET", *api_expires);
    *auth_msg = fmt::format(
        R"({{"op": "auth.api", "args": ["{}", "{}", "{}"]}})",
        *api_key,
        *api_expires,
        *api_sign);
  }

 protected:
  AuthKey key_;
};
